# Author ： chosen-yn
import uuid
from libs.al_pay import GATEWAY, alipay
from rest_framework import serializers
from .models import Order, OrderDetail
from rest_framework.exceptions import APIException
from course.models import Course
from django.conf import settings


class PaySerializer(serializers.ModelSerializer):
    # courses 不是表的字段，需要重写
    # courses=serializers.ListField()  # 这次我们不用,使用它后续还要查出一个个课程对象

    # 因为前端传入的是 'courses':[1,3,4]--》可以使用 PrimaryKeyRelatedField ，会去数据源 [Course.objects.all()]中做映射
    # 映射完后变成了 courses:[id为1的课程对象,id为3的课程对象,id为4的课程对象]
    courses = serializers.PrimaryKeyRelatedField(queryset=Course.objects.all(), many=True)

    class Meta:
        model = Order
        fields = ['subject', 'total_amount', 'pay_type', 'courses']

    def validate(self,
                 attrs):  # {'subject':课程名,'total_amount':总价格,'pay_type':1, courses:[id为1的课程对象,id为3的课程对象,id为4的课程对象]}
        # 1 校验数据是否正确【订单总价校验】--》total_amount 和 courses 比较价格是否正确
        total_amount = self._check_total_amount(attrs)

        # 2 生成订单号--》唯一的--》uuid
        out_trade_no = self._get_out_trade_no()

        # 3 获取支付人 --》当前登录用户
        user = self._get_user()

        # 4 获取支付链接--》支付宝
        self._get_pay_url(out_trade_no, total_amount, attrs.get('subject'))

        # 5 入库(两个表)的信息准备：Order,OrderDetail
        self._before_create(attrs, user, out_trade_no)
        return attrs

    def _check_total_amount(self, attrs):
        # 1 取出前端传入的价格
        total_amount = attrs.get('total_amount')
        # 2 循环课程对象，累加价格
        real_total_amount = 0
        courses = attrs.get('courses')
        for course in courses:
            real_total_amount += course.price
        # 3 比较，如果不一样，抛出异常
        if total_amount == real_total_amount:
            return real_total_amount
        else:
            raise APIException('课程价格错误')

    def _get_out_trade_no(self):
        # 永不重复的唯一id号
        return str(uuid.uuid4())

    def _get_user(self):
        # 当前登录用户
        return self.context.get('request').user

    def _get_pay_url(self, out_trade_no, total_amount, subject):
        pay_url = alipay.api_alipay_trade_page_pay(
            out_trade_no=out_trade_no,
            total_amount=float(total_amount),
            subject=subject,
            return_url=settings.RETURN_URL,  # get 回调--》前端
            notify_url=settings.NOTIFY_URL  # post 回调 --》后端
        )
        self.context['pay_url'] = GATEWAY + pay_url

    def _before_create(self, attrs, user, out_trade_no):
        # attrs ={'courses':[对象,],'total_amount':0.1,'subject':课程名,'pay_type':1}
        attrs['user'] = user
        attrs['out_trade_no'] = out_trade_no

    def create(self,
               validated_data):  # # {'courses':[对象,],'total_amount':0.1,'subject':课程名,'pay_type':1,user,out_trade_no}
        courses = validated_data.pop('courses')
        order = Order.objects.create(**validated_data)
        # 存订单详情
        for course in courses:
            OrderDetail.objects.create(order=order, course=course, price=course.price, real_price=course.price)
        return order
